package main

import (
	"context"
	"flag"
	"fmt"
	"kaiyue_testedge/testedge"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"
)

const (
	CLIENT = "client"
	SERVER = "server"
)

var (
	srcFilePath string
	linkNum int
	clientConnectTimeout int
	readWriteDataTimeout int
	times int
	network string
	direction string
	shorLongFlag string
	buffersize int64
	host string
	port string
)

var (
	t1 time.Time
	t2 time.Time
)

/*
	对k客户端参数进行初始化
*/
func modelInitArgs(ctx context.Context) (string, string, string) {
	//读取初始化默认参数
	var a = testedge.InitConnect()
	//解析参数
	flag.Parse()

	//设置客户端外部参数命令
	client := flag.NewFlagSet("client", flag.ExitOnError)

	client.StringVar(&srcFilePath, "c", a.SrcFilePath, "读取文件的所在路径")
	client.IntVar(&linkNum,"P",  a.LinkNum, "最大链接数")
	client.IntVar(&clientConnectTimeout,"ct",  a.ClientConnectTimeout, "客户端链接超时时间")
	//client.IntVar(&readWriteDataTimeout,"rt",  a.ReadWriteDataTimeout, "读写数据超时时间")
	client.IntVar(&times,"t",  a.Times, "维持最长时间")
	client.StringVar(&network,"n", a.Network, "网络类型: [ tcp | tcp4 | tcp6 ]")
	client.StringVar(&host,"a", a.Host, " 网络地址IP: 172.0.0.1")
	client.StringVar(&port,"p", a.Port, " 网络地址端口:8989")
	client.Int64Var(&buffersize,"b", a.MaxBuffer, "设置收发缓冲区大小")
	client.StringVar(&direction,"d", "", "网络的方向选择:[ line ]")
	client.StringVar(&shorLongFlag,"f", testedge.SHORT, "网络数据发送方式:[ short | long ]")

	//设置server端外部参数命令
	server := flag.NewFlagSet("server", flag.ExitOnError)

	server.IntVar(&clientConnectTimeout,"ct",  a.ClientConnectTimeout, "客户端链接超时时间")
	server.IntVar(&readWriteDataTimeout,"rt",  a.ReadWriteDataTimeout, "读写数据超时时间")
	server.StringVar(&network,"n", a.Network, "网络类型：[ tcp | tcp4 | tcp6 ]")
	server.StringVar(&port,"p", a.Port, " 网络地址端口:8989")
	server.StringVar(&direction,"d", "", "网络的方向选择:[ hole ]")
	server.StringVar(&shorLongFlag,"f", testedge.SHORT, "网络数据发送方式:[ short | long ]")
	server.Int64Var(&buffersize,"b", a.MaxBuffer, "设置收发缓冲区大小")

	//对参数进行解析
	flags := flag.Args()
	usage := "WARNING: ./main [ server | client ] ....!!"
	if len(flags) < 1 {
		fmt.Println(usage)
		return "", "", ""
	}

	switch flags[0] {
	case SERVER:
		err := server.Parse(flags[1:])
		if err != nil {
			return "", "", ""
		}
		//读入server参数并初始化
		connection  := testedge.Connects{
			Network:              network,
			Port: 				  port,
			ClientConnectTimeout: clientConnectTimeout,
			ReadWriteDataTimeout: readWriteDataTimeout,
			Direction:            direction,
			ShorLongFlag:         shorLongFlag,
			MaxBuffer: 			  buffersize,
		}
		go connection.Server(ctx)

	case CLIENT:
		err := client.Parse(flags[1:])
		if err != nil {
			return "", "", ""
		}
		connection := testedge.Connects{
			SrcFilePath:          srcFilePath,
			Network:              network,
			Host: 				  host,
			Port:				  port,
			LinkNum:              linkNum,
			Times:                times,
			ClientConnectTimeout: clientConnectTimeout,
			ReadWriteDataTimeout: readWriteDataTimeout,
			Direction:            direction,
			ShorLongFlag:         shorLongFlag,
			MaxBuffer: 			  buffersize,
		}
		go connection.Client(ctx)

	default:
		return "", "", ""
	}
	
	return flags[0], direction, shorLongFlag
}

func PrintGroupNumInfo(ctx context.Context, mode string, flags string)  {
	for {
		select {
		case <- ctx.Done():
			return
		default:
			if mode == CLIENT && flags == testedge.LONG {
				fmt.Println("================NumGoroutine:====================", runtime.NumGoroutine())
				time.Sleep(time.Second * 2)
			} else {
				//增加功能
				return
			}
		}
	}
}

func SetTimeFlagTrue()  {
	testedge.Lock.Lock()
	testedge.TimeAfterFlag = true
	testedge.Lock.Unlock()
}

func checkClientTimeOut(mode string) {
	if mode == CLIENT {
		<-time.After(time.Duration(times) * time.Second)
		t2 = time.Now()
		os.Exit(1)
		fmt.Printf("\n========================time after %ds !======================\n", times)
	}
}

/*
主函数
 */
func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	//首先对命令参数进行检查即（client/server）
	mode, directions, shorlongflags := modelInitArgs(ctx)
	//第一个参数输入错误
	if mode == "" {
		return
	}
	
	//开始计时
	t1 = time.Now()
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)

	//对客户端进行协程数目打印
	go PrintGroupNumInfo(ctx, mode, shorlongflags)
	//检查客户端超时
	go checkClientTimeOut(mode)

	//接收到中断信号
	<-signals
	cancel()
	fmt.Println("等待处理已接收的链接....")

	// 等待所有任务完成，设置超时机制
    done := make(chan struct{})
    go func() {
		//testedge.Groupflags.Wait()
		close(testedge.PoolOffchannel)
        close(done)
    }()

	//对超时和中断信号进行监测
	select {
	case <-done:
		t2 = time.Now()
		fmt.Println("已完成，退出任务!")
		break
	case <- time.After(5 * time.Second):
		fmt.Println("处理任务超时，退出任务!")
		break
	}

	//只对客户端的中断命令进行打印
	if mode == SERVER {
		return
	}

	diffTime := t2.Sub(t1).Seconds()
	//仅对双向传输的数据进行计算打印
	testedge.PrintConclulateInfo(directions, diffTime)
	os.Exit(1)
}

